package com.qf.myshop.shop_user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qf.myshop.shop_entity.ResultData;
import com.qf.myshop.shop_entity.User;
import com.qf.myshop.shop_user.dao.UserDAO;
import com.qf.myshop.shop_user.service.UserService;
import com.qf.myshop.shop_utils.MD5Utils;
import com.qf.myshop.shop_utils.MessageCodeConstants;
import com.qf.myshop.shop_utils.TokenUtil;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.UUID;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserDAO userDAO;
    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public ResultData save(User user) {
        // 随机生成一个盐值
        final String salt = UUID.randomUUID().toString().substring(3, 8);
        user.setSalt(salt);
        // 分配一个用户编号
        user.setCode("10001");
        user.setStatus(1); // 注册后自动激活，后期可以采用短信验证或者邮箱验证。
        // 密码加盐md5
        String newPassword = MD5Utils.md5(user.getPassword() + salt);
        user.setPassword(newPassword);
        final int i = userDAO.insert(user);
        if (i > 0){
            return ResultData.createSuccessJsonResult(null);
        }
        return ResultData.createFailJsonResult(MessageCodeConstants.REGISTER_FAIL, "注册失败");
    }

    @Override
    public ResultData login(User user) {
        final QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("u_name", user.getName());
        final User user1 = userDAO.selectOne(wrapper);
        if (user1 == null){
            return ResultData.createFailJsonResult(MessageCodeConstants.LOGIN_FAIL, "用户名或密码错误");
        }else{
            final String md5 = MD5Utils.md5(user.getPassword() + user1.getSalt());
            if (md5.equals(user1.getPassword())){
                // 登录成功需要生成jwt
                // 将用户信息转换成json格式，并生成token
                user1.setPassword(null);
                ObjectMapper mapper = new ObjectMapper();
                String s = null;
                try {
                    s = mapper.writeValueAsString(user1);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                final String token = TokenUtil.createToken(s);
                // 将用户email写入redis，设置一个超时时间
                String email = user1.getEmail();
                final BoundValueOperations operations = redisTemplate.boundValueOps(email);
                operations.set("time", Duration.ofMinutes(30));
                return ResultData.createSuccessJsonResult(token);
            }else {
                return ResultData.createFailJsonResult(MessageCodeConstants.LOGIN_FAIL, "用户名或密码错误");
            }
        }
    }

    @Override
    public ResultData check(String token) {
        // 1、验证token
        final ResultData data = TokenUtil.verifyJWT(token);
        if (data.getCode().equals("10000")){
            // 验证是否超时
            // 得到当前用户信息
            String jsonString = (String) data.getData();
            ObjectMapper mapper = new ObjectMapper();
            try {
                final User user = mapper.readValue(jsonString, User.class);
                final String email = user.getEmail();
                final BoundValueOperations operations = redisTemplate.boundValueOps(email);
                if (operations.get() == null){
                    return ResultData.createFailJsonResult(MessageCodeConstants.LOGIN_TIME_OUT, "登录已超时，请重新登录");
                }else{
                    operations.set("time", Duration.ofMinutes(30));
                    return ResultData.createSuccessJsonResult(null);
                }
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return ResultData.createFailJsonResult(MessageCodeConstants.LOGIN_TIME_OUT, "登录已超时，请重新登录");
            }
            // 2、刷新token
        }else{
            return data;
        }
    }
}
